package com.winhxd.b2c.order.service.impl;

import com.winhxd.b2c.common.cache.Cache;
import com.winhxd.b2c.common.cache.Lock;
import com.winhxd.b2c.common.cache.RedisLock;
import com.winhxd.b2c.common.constant.BusinessCode;
import com.winhxd.b2c.common.constant.CacheName;
import com.winhxd.b2c.common.domain.order.enums.*;
import com.winhxd.b2c.common.domain.order.model.OrderAfterSaleDetail;
import com.winhxd.b2c.common.domain.order.model.OrderInfo;
import com.winhxd.b2c.common.domain.order.model.OrderLog;
import com.winhxd.b2c.common.exception.BusinessException;
import com.winhxd.b2c.common.mq.MQDestination;
import com.winhxd.b2c.common.mq.MQHandler;
import com.winhxd.b2c.common.mq.StringMessageListener;
import com.winhxd.b2c.common.mq.StringMessageSender;
import com.winhxd.b2c.common.util.JsonUtil;
import com.winhxd.b2c.order.dao.OrderAfterSaleDetailMapper;
import com.winhxd.b2c.order.dao.OrderInfoMapper;
import com.winhxd.b2c.order.dao.OrderLogMapper;
import com.winhxd.b2c.order.service.OrderAfterSaleDetailService;
import com.winhxd.b2c.order.service.OrderService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.Calendar;
import java.util.Date;

/**
 * @description: 订单消费者
 * @author: liuhanning
 * @create: 2019-01-11 15:09
 **/
public class OrderMessageHandler {
    private static final Logger logger = LoggerFactory.getLogger(OrderMessageHandler.class);

    private static final int ORDER_UPDATE_LOCK_EXPIRES_TIME = 5000;

    //由于mq延时消息  最长时间不能超过Integer.MAX_VALUE，所以要做到 时间收尾交接的方式发送
    //自动确认收货  默认间隔发送时间（20天发送一次）毫秒
    public static final int INTERVAL_SEND_TIME = 20*24*60*60*1000;

    @Autowired
    OrderInfoMapper orderInfoMapper;
    @Autowired
    OrderService orderService;
    @Autowired
    private Cache cache;
    @Autowired
    private OrderAfterSaleDetailMapper afterSaleDetailMapper;
    @Autowired
    private StringMessageSender stringMessageSender;
    @Autowired
    OrderAfterSaleDetailService orderAfterSaleDetailService;
    @Autowired
    private OrderLogMapper orderLogMapper;

    @Transactional(rollbackFor = Exception.class)
    @StringMessageListener(value = MQHandler.OUTLET_ORDER_PAY_TIMEOUT_DELAYED_HANDLER)
    public void orderPayTimeOut(String orderNo) {
        if (StringUtils.isBlank(orderNo)) {
            throw new BusinessException(BusinessCode.ORDER_NO_EMPTY);
        }
        String lockKey = CacheName.CACHE_KEY_MODIFY_ORDER + orderNo;
        Lock lock = new RedisLock(cache, lockKey, ORDER_UPDATE_LOCK_EXPIRES_TIME);
        try {
            lock.lock();
            OrderInfo orderInfo = orderInfoMapper.selectByOrderNo(orderNo);
            if (orderInfo == null) {
                logger.info("订单号：{}未找到对应订单，无法执行订单未支付超时处理", orderNo);
                return;
            }
            if (orderInfo.getStatus() != OrderStatusEnum.WAIT_PAY.getStatusCode()) {
                logger.info("订单：{} 状态：{} 非待付款状态，无需进行超时取消操作", orderNo,
                        orderInfo.getStatus());
                return;
            }
            //取消
            logger.info("订单号：{}，订单自动取消开始", orderNo);
            orderService.orderCancel(orderInfo, "超时未付款取消", OrderStatusEnum.CLOSE.getStatusCode(),
                    OrderExtendStatusEnum.AUTO_CENCEL.getStatusCode(), 14, "4",OrderOperationPropertyEnum.CLOSE_ORDER.getPropertyDes());
            logger.info("订单号：{}，订单自动取消结束", orderNo);
        } finally {
            lock.unlock();
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @StringMessageListener(value = MQHandler.OUTLET_ORDER_AUTO_RECEIVING_HANDLER)
    public void orderAutoReceiving(String orderNo) {
        if (StringUtils.isBlank(orderNo)) {
            logger.info("订单号：{}，订单自动收货订单号为空", orderNo);
            throw new BusinessException(BusinessCode.ORDER_NO_EMPTY);
        }
        logger.info("订单号：{}，订单自动收货开始", orderNo);

        OrderInfo orderInfo = orderInfoMapper.selectByOrderNo(orderNo);
        if (orderInfo == null) {
            logger.info("订单号：{}未找到对应订单，无法执行订单闭环处理", orderNo);
            return;
        }

        //由于mq延时消息  最长时间不能超过Integer.MAX_VALUE，所以要做到 时间收尾交接的方式发送
        //发货时间
        long sendTime = Long.valueOf(0);
        if(null!= orderInfo.getSendTime()){
            Calendar c1 = Calendar.getInstance();
            c1.clear();
            c1.setTime(orderInfo.getSendTime());
            sendTime = c1.getTimeInMillis() ;
        }
        //自动收货天数
        long autoTime = Long.valueOf(0);
        if(null != orderInfo.getAutoReceiveDay()){
            autoTime = orderInfo.getAutoReceiveDay()*24*60*60*1000;
        }
        //自动收货时间
        sendTime = sendTime + autoTime;
        //当前时间
        long currentTime = System.currentTimeMillis();
        //判断当前时间和自动收货时间的时间差
        long intervalTime = sendTime - currentTime;

        if(intervalTime >= INTERVAL_SEND_TIME){
            //当前时间 距离 自动收货时间 大于等于intervalSendTime
            logger.info("订单号：{}，自动发送间隔时间{}毫秒，当前时间距离自动收货时间差{}毫秒，订单未到自动收货时间，继续发送延时消息，", orderNo,INTERVAL_SEND_TIME,intervalTime);
            stringMessageSender.send(MQDestination.OUTLET_ORDER_AUTO_RECEIVING, orderInfo.getOrderNo(), INTERVAL_SEND_TIME);
        }else if(intervalTime < INTERVAL_SEND_TIME && intervalTime>0){
            //当前时间 距离 自动收货时间 小于 intervalSendTime
            logger.info("订单号：{}，自动发送间隔时间{}毫秒，当前时间距离自动收货时间差{}毫秒，订单未到自动收货时间，发送延时消息，", orderNo,INTERVAL_SEND_TIME,intervalTime);
            stringMessageSender.send(MQDestination.OUTLET_ORDER_AUTO_RECEIVING, orderInfo.getOrderNo(), (int)intervalTime);
        }else {
            orderService.orderComplete(orderInfo);
            logger.info("订单号：{}，订单自动收货结束", orderNo);
        }
    }



    /**
     * @Description 退换货未输入物流信息
     * @author lining
     * @date 2019/1/13 10:55:13
     * @param afterSaleDetailId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @StringMessageListener(value = MQHandler.OUTLET_ORDER_RETURNING_TIMEOUT_DELAYED_HANDLER)
    public void orderReturningTimeOut(String afterSaleDetailId) {
        logger.info("退换货未输入物流信息-----orderReturningTimeOut-----start");
        //验证售后是否强制关闭
        orderAfterSaleDetailService.validateCloseAfterSaleStatus(Long.valueOf(afterSaleDetailId));
        String lockKey = CacheName.CACHE_KEY_RETURNING_AFTER_SALE + afterSaleDetailId;
        Lock lock = new RedisLock(cache, lockKey, ORDER_UPDATE_LOCK_EXPIRES_TIME);
        OrderAfterSaleDetail afterSaleDetail = afterSaleDetailMapper.selectByPrimaryKey(Long.parseLong(afterSaleDetailId));
        if (lock.tryLock()) {
            try {
                if(afterSaleDetail.getViewStatus().intValue()== AfterSaleViewStatusEnum.CHECKED.getTypeCode().intValue()){
                    //修改售后状态
                    this.updateAfterSale(afterSaleDetail);
                    //售后日志
                    this.saveOrderLogCloseAfterSale(afterSaleDetail);
                    //售后完成修改各种状态
                    orderAfterSaleDetailService.updateOrderStatus(afterSaleDetail.getOrderNo());
                }else {
                    logger.info("已输入物流信息！");
                }
            } finally {
                lock.unlock();
            }
        } else {
            throw new BusinessException(BusinessCode.CODE_440603);
        }
    }

    /**
     * @Description 修改售后状态
     * @author lining
     * @date 2019/1/23 16:10:13
     * @param afterSaleDetail
     * @return
     */
    private void updateAfterSale(OrderAfterSaleDetail afterSaleDetail){
        OrderAfterSaleDetail detail = new OrderAfterSaleDetail();
        detail.setId(afterSaleDetail.getId());
        detail.setAfterSaleStatus(AfterSaleStatusEnum.CLOSED.getTypeCode());
        detail.setCompleteStatus(AfterSaleCompleteStatusEnum.COMPLETED.getTypeCode());
        detail.setViewStatus(AfterSaleViewStatusEnum.CLOSED.getTypeCode());
        Date now = new Date();
        detail.setUpdated(now);
        detail.setCloseTime(now);
        detail.setCompleteTime(now);
        detail.setUpdatedBy(UpdatedByEnum.AFTERSALE_RETURNING.getTypeCode());
        afterSaleDetailMapper.updateByPrimaryKeySelective(detail);
    }

    /**
     *  售后日志
     * @param afterSaleDetail
     */
    private void saveOrderLogCloseAfterSale(OrderAfterSaleDetail afterSaleDetail){
        OrderLog orderLog = new OrderLog();
        orderLog.setOrderNo(afterSaleDetail.getOrderNo());
        orderLog.setSkuId(afterSaleDetail.getSkuId());
        String operationPropertity = OrderOperationPropertyEnum.HAND_CLOSE_AFTER_SALE_NO_EXPRESS.getPropertyDes();
        orderLog.setCreated(new Date());
        orderLog.setOperationProperty(operationPropertity);
        logger.info("售后-未输入物流信息售后日志-----saveOrderLogCloseAfterSale-----{}", JsonUtil.toJSONString(orderLog));
        orderLogMapper.insertSelective(orderLog);
    }
}
